package support

import (
	"github.com/gomodule/redigo/redis"
	"yuanchang/spider/http"
	"encoding/json"
)

const (
	redisConnError         = "get redis connection error"
	redisReplyConvertError = "reply convert error"
)

const (
	requestMashalError          = "The request Mashal error"
	requestUnMashalConvertError = "The unmashal value convert request error"
)

var (
	DefaultTopic = "wait_crawl_queue"
)

type RedisStore struct {
	Pool *redis.Pool
}

// from redis connection pool get a connect
func (r *RedisStore) GetConn() interface{} {
	return r.Pool.Get()
}

func (r *RedisStore) Push(req *http.Request) {
	var (
		ok      bool
		err     error
		content []byte
		conn    redis.Conn
	)
	if conn, ok = r.GetConn().(redis.Conn); !ok {
		return
	}
	defer conn.Close()

	// marshal request
	if content, err = req.Marshal(); err != nil {
		return
	}
	if _, err := conn.Do("LPUSH", DefaultTopic, string(content)); err != nil {

		return
	}
}

func (r *RedisStore) Pop() (*http.Request) {
	c := make(chan *http.Request)
	go func() {
		var (
			ok      bool
			err     error
			content []byte
			conn    redis.Conn
			reply   interface{}
		)

		if conn, ok = r.GetConn().(redis.Conn); !ok {
			c <- nil
			return
		}
		defer conn.Close()
		if reply, err = conn.Do("LPOP", DefaultTopic); err != nil {
			c <- nil
			return
		}
		if content, ok = reply.([]byte); !ok {
			c <- nil
			return
		}
		req := new(http.Request)
		// TODO
		if err = json.Unmarshal(content, req); err != nil {
			c <- nil
			return
		}
		c <- req
	}()

	return <-c
}

func NewRedisConnPool() *redis.Pool {
	redisPool := &redis.Pool{}
	// TODO use config
	redisPool.MaxIdle = 10
	redisPool.Dial = func() (redis.Conn, error) {
		// TODO use config
		return redis.Dial("tcp", "127.0.0.1:23761")
	}
	return redisPool
}

